package com.blue.base.mongo;

import com.blue.base.common.bean.page.PageParam;
import com.google.common.collect.Lists;
import com.mongodb.client.result.UpdateResult;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * Mongodb工具类
 *
 * @author liulei
 * @version 2.0
 */
@Slf4j
@Data
@Component
@ConditionalOnProperty(value = "spring.data.mongodb")
public class MongoOperateApi {

    @Resource
    private MongoTemplate mongoTemplate;

    public boolean insert(Object object) {
        if (Objects.isNull(object)) {
            log.info("no records to insert to mongo ");
            return true;
        }
        try {
            mongoTemplate.insert(object);
            return true;
        } catch (Exception e) {
            log.error("insert|single|mongodb|rows|error", e);
        }
        return false;
    }

    /**
     * 插入记录
     *
     * @param list 待插入的记录
     * @return 结果
     */
    public boolean insertRows(List<?> list) {
        if (list.isEmpty()) {
            log.info("no records to insert to mongo ");
            return true;
        }
        try {
            mongoTemplate.insert(list, list.get(0).getClass());
            return true;
        } catch (Exception e) {
            log.error("insert|multi|mongodb|rows|error", e);
        }
        return false;
    }

    /**
     * 根据主键列表删除记录
     *
     * @param list 记录
     * @return 结果
     */
    public Integer deleteByPrimaryKey(List<?> list, Class<?> clazz) {
        try {
            Criteria criteria = Criteria.where("id").in(list);
            Query query = new Query().addCriteria(criteria);
            List<?> remove = mongoTemplate.findAllAndRemove(query, clazz);
            log.info("delete the primary key of[{}]", list);
            return remove.size();
        } catch (Exception e) {
            log.error("delete|mongodb|rows|error", e);
        }
        return 0;
    }

    /**
     * 根据主键修改
     *
     * @param queryCriteria         待修改的where查询条件
     * @param updateColumnAndValues update待set修改的列及值
     * @param clazz                 对应实体类
     * @return 受影响的行数
     */
    public Long update(Criteria queryCriteria, Map<String, Object> updateColumnAndValues, Class<?> clazz) {
        try {
            Query query = new Query().addCriteria(queryCriteria);
            Update update = new Update();
            // 批量设置column-value的值
            for (Map.Entry<String, Object> entry : updateColumnAndValues.entrySet()) {
                update.set(entry.getKey(), entry.getValue());
            }
            UpdateResult modify = mongoTemplate.updateMulti(query, update, clazz);
            return modify.getModifiedCount();
        } catch (Exception e) {
            log.error("update|mongodb|rows|error", e);
        }
        return 0L;
    }

    /**
     * 主键查询
     *
     * @param id 主键
     * @return 结果集
     */
    public <T> T queryByPrimaryKey(Long id, Class<T> clazz) {
        return mongoTemplate.findById(id, clazz);
    }

    /**
     * 获取Like查询模式pattern
     *
     * @param value 匹配的值
     * @return pattern
     */
    public Pattern getLikeQueryPattern(String value) {
        String regex = String.format("%s%s%s", "^.*", Objects.requireNonNull(value, "模糊匹配值不能为空"), ".*$");
        return Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
    }

    /**
     * @param queryCriteria 查询表达式
     * @return 结果集合
     */
    public <T> List<T> queryList(Criteria queryCriteria, Class<T> clazz) {
        try {
            Query query = new Query();
            query.addCriteria(queryCriteria);
            return mongoTemplate.find(query, clazz);
        } catch (Exception e) {
            log.error("query|mongodb|rows|error", e);
        }
        return Lists.newArrayList();
    }

    /**
     * 简单查询
     */
    public <T> List<T> queryList(Query query, Class<T> clazz) {
        return this.mongoTemplate.find(query, clazz);
    }

    /**
     * 多条件分页查询
     *
     * @param query 查询表达式
     * @param sort  分页表达式
     * @param clazz 返回集合实体类型
     * @param <T>   返回结果泛型
     * @return 集合
     */
    public <T> List<T> queryPage(Query query, Sort sort, PageParam pageParam, Class<T> clazz) {
        if (pageParam.getCurrent() <= 0) {
            pageParam.setCurrent(1);
        }
        try {
            int totalCount = (int) mongoTemplate.count(query, clazz);
            int offset = pageParam.getSize() * (pageParam.getCurrent() - 1);
            List<T> result = mongoTemplate.find(query.with(sort).skip(offset).limit(pageParam.getSize()), clazz);
            log.info("offset:{},pageSize:{},totalCount:{},result:{}", offset, pageParam.getSize(), totalCount, result);
            return result;
        } catch (Exception e) {
            log.error("query|page|mongodb|rows|error", e);
        }
        return Lists.newArrayList();
    }
}
